Public Class Trade
    Enum ETradeType
        [Long]
        [Short]
    End Enum
    Enum ETradePriceType
        OpeningTrade
        ClosingTrade
    End Enum

    Public IsAlive As Boolean

    'Initial 
    Public Type As ETradeType
    Public Pair As CurrencyPair
    Public InitialAmount As AmountOfMoney

    Public OpenDate As Date
    Dim OpenBidPrice As Double
    Dim SpreadAtTradeOpen As Double

    'Current
    Dim CurrentSpread As Double
    Dim CurrentBidPrice As Double
    Dim CurrentAmount As AmountOfMoney

    Public ReadOnly Property OpenPrice() As Double
        Get
            Return GetEfectiveForTradeTypePrice(Me.OpenBidPrice, Me.SpreadAtTradeOpen, ETradePriceType.OpeningTrade, Me.Type)
        End Get
    End Property
    Public ReadOnly Property CurrentClosePrice() As Double
        Get
            Return GetEfectiveForTradeTypePrice(Me.CurrentBidPrice, Me.CurrentSpread, ETradePriceType.ClosingTrade, Me.Type)
        End Get
    End Property
    Public ReadOnly Property CurrentPriceDiference() As Double
        Get
            Return Me.CurrentClosePrice - Me.OpenPrice
        End Get
    End Property
    Public ReadOnly Property CurrentProfitNumericValue() As Double
        Get
            Return Me.CurrentAmount.Amount * CurrentProfitInPips * CurrencyPair.GetPipValueInSpecifiedCurrency(Me.CurrentClosePrice, Me.Pair.SignificantDecimalPlacesInExchangeRateValue, Me.CurrentAmount.AmountCurrency, Me.Pair.QuoteCurrency, General.CurrencyPairs, General.Currencies)
        End Get
    End Property
    Public ReadOnly Property CurrentProfitInPips() As Double
        Get
            Return GetProfitInPips(CurrentPriceDiference, Me.Pair.SignificantDecimalPlacesInExchangeRateValue, Me.Type)
        End Get
    End Property




    'Final
    Public Class PartiallyClosedTrade
        Public [Date] As Date
        Public BidPrice As Double
        Public NumericAmount As Double
        Public Spread As Double
        Sub New(ByVal closeDate As Date, ByVal closeBidPrice As Double, ByVal closeNumericAmount As Double, ByVal spreadAtTradeClose As Double)
            Me.[Date] = closeDate
            Me.BidPrice = closeBidPrice
            Me.NumericAmount = closeNumericAmount
            Me.Spread = spreadAtTradeClose
        End Sub
    End Class
    Public PartiallyClosedTrades As New List(Of PartiallyClosedTrade)


    Private Function IsValidIndex(ByVal index As Integer) As Boolean
        If PartiallyClosedTrades.Count - 1 >= index Then
            Return True
        Else
            Return False
        End If
    End Function
    Public ReadOnly Property ClosePrice(ByVal index As Integer) As Double
        Get
            If IsValidIndex(index) Then
                Return GetEfectiveForTradeTypePrice(PartiallyClosedTrades(index).BidPrice, PartiallyClosedTrades(index).Spread, ETradePriceType.ClosingTrade, Me.Type)
            Else
                Throw New Exception("Not valid index in PartiallyClosedTrades object")
            End If
        End Get
    End Property

    Public ReadOnly Property PartialTradePriceDiference(ByVal index As Integer) As Double
        Get
            Return Me.ClosePrice(index) - Me.OpenPrice
        End Get
    End Property
    Public ReadOnly Property PartialTradeProfitNumericAmount(ByVal Index As Integer) As Double
        Get
            Return Me.PartiallyClosedTrades(Index).NumericAmount * PartialTradeProfitInPips(Index) * CurrencyPair.GetPipValueInSpecifiedCurrency(Me.ClosePrice(Index), Me.Pair.SignificantDecimalPlacesInExchangeRateValue, Me.CurrentAmount.AmountCurrency, Me.Pair.QuoteCurrency, General.CurrencyPairs, General.Currencies)
        End Get
    End Property
    Public ReadOnly Property PartialTradeProfitInPips(ByVal Index As Integer) As Double
        Get
            Return GetProfitInPips(PartialTradePriceDiference(Index), Me.Pair.SignificantDecimalPlacesInExchangeRateValue, Me.Type)
        End Get
    End Property
    Public ReadOnly Property TotalPartialTradesProfitNumericAmount() As Double
        Get
            Dim Total As Double = 0
            For i As Integer = 0 To PartiallyClosedTrades.Count - 1
                Total += PartialTradeProfitNumericAmount(i)
            Next
            Return Total
        End Get
    End Property
    Public Shared Function GetProfitInPips(ByVal currentPriceDiference As Double, ByVal significantDecimalPlacesInExchangeRateValue As Integer, ByVal tradeType As ETradeType) As Double
        Select Case tradeType
            Case ETradeType.Long
                Return (currentPriceDiference) / CurrencyPair.GetPipValueInQuoteCurrency(significantDecimalPlacesInExchangeRateValue)
            Case ETradeType.Short
                Return (-currentPriceDiference) / CurrencyPair.GetPipValueInQuoteCurrency(significantDecimalPlacesInExchangeRateValue)
        End Select
    End Function
    Public Shared Function GetEfectiveForTradeTypePrice(ByVal BidPrice As Double, ByVal Spread As Double, ByVal TradePriceType As ETradePriceType, ByVal TradeType As ETradeType) As Double
        Select Case TradePriceType
            Case ETradePriceType.ClosingTrade
                Select Case TradeType
                    Case Trade.ETradeType.Long
                        Return BidPrice
                    Case Trade.ETradeType.Short
                        Return BidPrice + Spread
                End Select
            Case ETradePriceType.OpeningTrade
                Select Case TradeType
                    Case Trade.ETradeType.Long
                        Return BidPrice + Spread
                    Case Trade.ETradeType.Short
                        Return BidPrice
                End Select
        End Select
    End Function






#Region "Trade Managment Subs"
    Public Sub CloseTrade(ByVal closeBidPrice As Double, ByVal spreadAtTradeClose As Double, ByVal closeDate As Date)
        PartiallyCloseTrade(Me.CurrentAmount.Amount, closeBidPrice, spreadAtTradeClose, closeDate)
    End Sub
    Public Sub PartiallyCloseTrade(ByVal AmountNumericValue As Double, ByVal closeBidPrice As Double, ByVal spreadAtTradeClose As Double, ByVal closeDate As Date)
        If AmountNumericValue > Me.CurrentAmount.Amount Then Throw New Exception("The closing amount can't be greater than the current amount of money in the trade")

        PartiallyClosedTrades.Add(New PartiallyClosedTrade(closeDate, closeBidPrice, AmountNumericValue, spreadAtTradeClose))
        Me.CurrentAmount.Amount -= AmountNumericValue

        CheckIfIsFullyClosed()
    End Sub
    Private Sub CheckIfIsFullyClosed()
        If CurrentAmount.Amount = 0 Then
            Me.IsAlive = False
        End If
    End Sub
    Public Sub OpenTrade(ByVal amount As AmountOfMoney, ByVal openBidPrice As Double, ByVal spreadAtTradeOpen As Double, ByVal openDate As Date)
        Me.OpenBidPrice = openBidPrice
        Me.OpenDate = openDate
        Me.SpreadAtTradeOpen = spreadAtTradeOpen
        Me.CurrentAmount = amount.Clone
        Me.InitialAmount = amount.Clone
        IsAlive = True
    End Sub
    Public Sub RefreshTradeStatus(ByVal currentBidPrice As Double, ByVal currentSpread As Double)
        Me.CurrentSpread = currentSpread
        Me.CurrentBidPrice = currentBidPrice
    End Sub
#End Region

#Region "New Subs"
    Sub New(ByVal amount As AmountOfMoney, ByVal pair As CurrencyPair, ByVal type As ETradeType, ByVal openBidPrice As Double, ByVal spreadAtTradeOpen As Double, ByVal openDate As Date)
        Me.New(pair, type)
        OpenTrade(amount, openBidPrice, spreadAtTradeOpen, openDate)
    End Sub
    Sub New(ByVal pair As CurrencyPair, ByVal type As ETradeType)
        Me.Pair = pair
        Me.Type = type
    End Sub
#End Region
End Class
